package com.kexio.enterprise.integration.file.impl;

import com.kexio.enterprise.integration.file.FileService;
import com.kexio.enterprise.integration.file.domain.FileInfo;
import com.kexio.enterprise.integration.file.metadata.FileMetadata;
import com.kexio.enterprise.integration.file.query.FileSearchCriteria;
import com.kexio.enterprise.integration.file.result.FileDownloadResult;
import com.kexio.enterprise.integration.file.result.FileUploadResult;
import com.kexio.enterprise.integration.file.statistics.StorageStatistics;
import com.kexio.enterprise.integration.common.PageResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 本地文件存储服务实现
 * 
 * 基于本地文件系统的文件存储实现
 * 
 * @author Kexio
 * @since 1.0.0
 */
public class LocalFileService implements FileService {

    private static final Logger log = LoggerFactory.getLogger(LocalFileService.class);

    private final String basePath;
    private final String baseUrl;
    private final Map<String, FileMetadata> fileMetadataCache = new ConcurrentHashMap<>();

    public LocalFileService(String basePath, String baseUrl) {
        this.basePath = basePath;
        this.baseUrl = baseUrl;
        initializeBasePath();
    }

    /**
     * 初始化基础路径
     */
    private void initializeBasePath() {
        try {
            Path baseDir = Paths.get(basePath);
            if (!Files.exists(baseDir)) {
                Files.createDirectories(baseDir);
                log.info("创建文件存储目录: {}", basePath);
            }
        } catch (IOException e) {
            throw new RuntimeException("初始化文件存储目录失败: " + basePath, e);
        }
    }

    @Override
    public FileUploadResult uploadFile(FileInfo fileInfo) {
        FileUploadResult result = new FileUploadResult();
        result.setUploadTime(LocalDateTime.now());

        try {
            // 生成文件ID和路径
            String fileId = generateFileId();
            String fileName = fileInfo.getFileName();
            if (!StringUtils.hasText(fileName)) {
                fileName = fileInfo.getOriginalFileName();
            }
            
            String filePath = generateFilePath(fileName, fileInfo.isTemporary());
            Path targetPath = Paths.get(basePath, filePath);
            
            // 创建目录
            Files.createDirectories(targetPath.getParent());
            
            // 写入文件
            long fileSize = 0;
            if (fileInfo.getInputStream() != null) {
                fileSize = Files.copy(fileInfo.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
            } else if (fileInfo.getFileBytes() != null) {
                Files.write(targetPath, fileInfo.getFileBytes());
                fileSize = fileInfo.getFileBytes().length;
            } else {
                throw new IllegalArgumentException("文件内容不能为空");
            }
            
            // 计算文件哈希
            String etag = calculateFileHash(targetPath);
            
            // 保存文件元数据
            FileMetadata metadata = new FileMetadata();
            metadata.setFileId(fileId);
            metadata.setFileName(fileName);
            metadata.setOriginalFileName(fileInfo.getOriginalFileName());
            metadata.setFilePath(filePath);
            metadata.setContentType(fileInfo.getContentType());
            metadata.setFileSize(fileSize);
            metadata.setEtag(etag);
            metadata.setCreateTime(LocalDateTime.now());
            metadata.setModifiedTime(LocalDateTime.now());
            metadata.setMetadata(fileInfo.getMetadata());
            metadata.setDirectory(false);
            metadata.setStorageClass("LOCAL");
            
            fileMetadataCache.put(fileId, metadata);
            
            // 设置返回结果
            result.setSuccess(true);
            result.setFileId(fileId);
            result.setFileName(fileName);
            result.setFilePath(filePath);
            result.setFileUrl(baseUrl + "/" + filePath);
            result.setFileSize(fileSize);
            result.setContentType(fileInfo.getContentType());
            result.setEtag(etag);
            result.setMetadata(fileInfo.getMetadata());
            
            log.info("文件上传成功: {} -> {}", fileName, filePath);
            
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            log.error("文件上传失败: {}", fileInfo.getFileName(), e);
        }
        
        return result;
    }

    @Override
    public FileUploadResult uploadFile(String fileName, InputStream inputStream, String contentType) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(fileName);
        fileInfo.setOriginalFileName(fileName);
        fileInfo.setInputStream(inputStream);
        fileInfo.setContentType(contentType);
        return uploadFile(fileInfo);
    }

    @Override
    public FileUploadResult uploadFile(String fileName, byte[] fileBytes, String contentType) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setFileName(fileName);
        fileInfo.setOriginalFileName(fileName);
        fileInfo.setFileBytes(fileBytes);
        fileInfo.setContentType(contentType);
        return uploadFile(fileInfo);
    }

    @Override
    public FileDownloadResult downloadFile(String fileId) {
        FileDownloadResult result = new FileDownloadResult();
        
        try {
            FileMetadata metadata = getFileMetadata(fileId);
            if (metadata == null) {
                result.setSuccess(false);
                result.setErrorMessage("文件不存在: " + fileId);
                return result;
            }
            
            return downloadFileByPath(metadata.getFilePath());
            
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            log.error("文件下载失败: {}", fileId, e);
        }
        
        return result;
    }

    @Override
    public FileDownloadResult downloadFileByPath(String filePath) {
        FileDownloadResult result = new FileDownloadResult();
        
        try {
            Path targetPath = Paths.get(basePath, filePath);
            if (!Files.exists(targetPath)) {
                result.setSuccess(false);
                result.setErrorMessage("文件不存在: " + filePath);
                return result;
            }
            
            // 读取文件
            byte[] fileBytes = Files.readAllBytes(targetPath);
            BasicFileAttributes attrs = Files.readAttributes(targetPath, BasicFileAttributes.class);
            
            result.setSuccess(true);
            result.setFileName(targetPath.getFileName().toString());
            result.setFileBytes(fileBytes);
            result.setFileSize(fileBytes.length);
            result.setLastModified(LocalDateTime.ofInstant(attrs.lastModifiedTime().toInstant(), ZoneId.systemDefault()));
            result.setEtag(calculateFileHash(targetPath));
            
            // 尝试获取内容类型
            try {
                String contentType = Files.probeContentType(targetPath);
                result.setContentType(contentType);
            } catch (IOException e) {
                log.debug("无法检测文件类型: {}", filePath);
            }
            
            log.debug("文件下载成功: {}", filePath);
            
        } catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            log.error("文件下载失败: {}", filePath, e);
        }
        
        return result;
    }

    @Override
    public boolean deleteFile(String fileId) {
        try {
            FileMetadata metadata = getFileMetadata(fileId);
            if (metadata == null) {
                return false;
            }
            
            boolean deleted = deleteFileByPath(metadata.getFilePath());
            if (deleted) {
                fileMetadataCache.remove(fileId);
            }
            return deleted;
            
        } catch (Exception e) {
            log.error("文件删除失败: {}", fileId, e);
            return false;
        }
    }

    @Override
    public boolean deleteFileByPath(String filePath) {
        try {
            Path targetPath = Paths.get(basePath, filePath);
            if (Files.exists(targetPath)) {
                Files.delete(targetPath);
                log.info("文件删除成功: {}", filePath);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("文件删除失败: {}", filePath, e);
            return false;
        }
    }

    @Override
    public Map<String, Boolean> batchDeleteFiles(List<String> fileIds) {
        Map<String, Boolean> results = new HashMap<>();
        for (String fileId : fileIds) {
            results.put(fileId, deleteFile(fileId));
        }
        return results;
    }

    @Override
    public FileMetadata getFileMetadata(String fileId) {
        return fileMetadataCache.get(fileId);
    }

    @Override
    public FileMetadata getFileMetadataByPath(String filePath) {
        try {
            Path targetPath = Paths.get(basePath, filePath);
            if (!Files.exists(targetPath)) {
                return null;
            }
            
            BasicFileAttributes attrs = Files.readAttributes(targetPath, BasicFileAttributes.class);
            
            FileMetadata metadata = new FileMetadata();
            metadata.setFileId(generateFileId());
            metadata.setFileName(targetPath.getFileName().toString());
            metadata.setFilePath(filePath);
            metadata.setFileSize(attrs.size());
            metadata.setCreateTime(LocalDateTime.ofInstant(attrs.creationTime().toInstant(), ZoneId.systemDefault()));
            metadata.setModifiedTime(LocalDateTime.ofInstant(attrs.lastModifiedTime().toInstant(), ZoneId.systemDefault()));
            metadata.setDirectory(attrs.isDirectory());
            metadata.setStorageClass("LOCAL");
            
            // 尝试获取内容类型
            try {
                String contentType = Files.probeContentType(targetPath);
                metadata.setContentType(contentType);
            } catch (IOException e) {
                log.debug("无法检测文件类型: {}", filePath);
            }
            
            return metadata;
            
        } catch (Exception e) {
            log.error("获取文件元数据失败: {}", filePath, e);
            return null;
        }
    }

    @Override
    public boolean fileExists(String fileId) {
        FileMetadata metadata = getFileMetadata(fileId);
        return metadata != null && fileExistsByPath(metadata.getFilePath());
    }

    @Override
    public boolean fileExistsByPath(String filePath) {
        Path targetPath = Paths.get(basePath, filePath);
        return Files.exists(targetPath);
    }

    @Override
    public FileUploadResult copyFile(String sourceFileId, String targetPath) {
        try {
            FileMetadata sourceMetadata = getFileMetadata(sourceFileId);
            if (sourceMetadata == null) {
                FileUploadResult result = new FileUploadResult();
                result.setSuccess(false);
                result.setErrorMessage("源文件不存在: " + sourceFileId);
                return result;
            }
            
            Path sourcePath = Paths.get(basePath, sourceMetadata.getFilePath());
            Path destPath = Paths.get(basePath, targetPath);
            
            Files.createDirectories(destPath.getParent());
            Files.copy(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
            
            // 创建新的文件信息
            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileName(destPath.getFileName().toString());
            fileInfo.setOriginalFileName(sourceMetadata.getOriginalFileName());
            fileInfo.setContentType(sourceMetadata.getContentType());
            fileInfo.setFilePath(targetPath);
            
            try (InputStream inputStream = Files.newInputStream(destPath)) {
                fileInfo.setInputStream(inputStream);
                return uploadFile(fileInfo);
            }
            
        } catch (Exception e) {
            FileUploadResult result = new FileUploadResult();
            result.setSuccess(false);
            result.setErrorMessage(e.getMessage());
            log.error("文件复制失败: {} -> {}", sourceFileId, targetPath, e);
            return result;
        }
    }

    @Override
    public boolean moveFile(String fileId, String targetPath) {
        try {
            FileMetadata metadata = getFileMetadata(fileId);
            if (metadata == null) {
                return false;
            }
            
            Path sourcePath = Paths.get(basePath, metadata.getFilePath());
            Path destPath = Paths.get(basePath, targetPath);
            
            Files.createDirectories(destPath.getParent());
            Files.move(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
            
            // 更新元数据
            metadata.setFilePath(targetPath);
            metadata.setModifiedTime(LocalDateTime.now());
            
            log.info("文件移动成功: {} -> {}", metadata.getFilePath(), targetPath);
            return true;
            
        } catch (Exception e) {
            log.error("文件移动失败: {} -> {}", fileId, targetPath, e);
            return false;
        }
    }

    @Override
    public boolean renameFile(String fileId, String newName) {
        try {
            FileMetadata metadata = getFileMetadata(fileId);
            if (metadata == null) {
                return false;
            }
            
            Path sourcePath = Paths.get(basePath, metadata.getFilePath());
            Path destPath = sourcePath.getParent().resolve(newName);
            
            Files.move(sourcePath, destPath, StandardCopyOption.REPLACE_EXISTING);
            
            // 更新元数据
            String newFilePath = sourcePath.getParent().toString().replace(basePath, "") + "/" + newName;
            metadata.setFileName(newName);
            metadata.setFilePath(newFilePath);
            metadata.setModifiedTime(LocalDateTime.now());
            
            log.info("文件重命名成功: {} -> {}", metadata.getFileName(), newName);
            return true;
            
        } catch (Exception e) {
            log.error("文件重命名失败: {} -> {}", fileId, newName, e);
            return false;
        }
    }

    @Override
    public String generatePresignedUrl(String fileId, int expireMinutes) {
        FileMetadata metadata = getFileMetadata(fileId);
        if (metadata == null) {
            return null;
        }
        
        // 本地文件服务直接返回文件URL
        return baseUrl + "/" + metadata.getFilePath();
    }

    @Override
    public String generateUploadPresignedUrl(String fileName, String contentType, int expireMinutes) {
        // 本地文件服务不支持预签名上传URL
        return null;
    }

    @Override
    public List<FileMetadata> listFiles(String directoryPath) {
        try {
            Path dirPath = Paths.get(basePath, directoryPath);
            if (!Files.exists(dirPath) || !Files.isDirectory(dirPath)) {
                return Collections.emptyList();
            }
            
            try (Stream<Path> paths = Files.list(dirPath)) {
                return paths.map(path -> {
                    String relativePath = Paths.get(basePath).relativize(path).toString();
                    return getFileMetadataByPath(relativePath);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
            }
            
        } catch (Exception e) {
            log.error("列出文件失败: {}", directoryPath, e);
            return Collections.emptyList();
        }
    }

    @Override
    public PageResult<FileMetadata> listFiles(String directoryPath, int page, int size) {
        List<FileMetadata> allFiles = listFiles(directoryPath);
        
        int totalElements = allFiles.size();
        int totalPages = (int) Math.ceil((double) totalElements / size);
        int start = page * size;
        int end = Math.min(start + size, totalElements);
        
        List<FileMetadata> pageContent = start < totalElements ? 
                allFiles.subList(start, end) : Collections.emptyList();
        
        PageResult<FileMetadata> result = new PageResult<>();
        result.setContent(pageContent);
        result.setTotalElements(totalElements);
        result.setTotalPages(totalPages);
        result.setPageNumber(page);
        result.setPageSize(size);
        
        return result;
    }

    @Override
    public List<FileMetadata> searchFiles(FileSearchCriteria criteria) {
        try {
            Path searchPath = Paths.get(basePath);
            if (StringUtils.hasText(criteria.getDirectoryPath())) {
                searchPath = Paths.get(basePath, criteria.getDirectoryPath());
            }
            
            if (!Files.exists(searchPath)) {
                return Collections.emptyList();
            }
            
            try (Stream<Path> paths = Files.walk(searchPath)) {
                return paths.filter(path -> !Files.isDirectory(path) || criteria.isIncludeDirectories())
                        .map(path -> {
                            String relativePath = Paths.get(basePath).relativize(path).toString();
                            return getFileMetadataByPath(relativePath);
                        })
                        .filter(Objects::nonNull)
                        .filter(metadata -> matchesSearchCriteria(metadata, criteria))
                        .limit(criteria.getLimit() > 0 ? criteria.getLimit() : Integer.MAX_VALUE)
                        .collect(Collectors.toList());
            }
            
        } catch (Exception e) {
            log.error("搜索文件失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public PageResult<FileMetadata> searchFiles(FileSearchCriteria criteria, int page, int size) {
        List<FileMetadata> allFiles = searchFiles(criteria);
        
        int totalElements = allFiles.size();
        int start = page * size;
        int end = Math.min(start + size, totalElements);
        
        List<FileMetadata> pageContent = start < totalElements 
            ? allFiles.subList(start, end) 
            : Collections.emptyList();
        
        return new PageResult<>(pageContent, totalElements, page, size);
    }

    @Override
    public StorageStatistics getStorageStatistics(String storageType, String bucket) {
        return getGlobalStorageStatistics(); // 本地存储不区分类型和桶
    }

    @Override
    public StorageStatistics getGlobalStorageStatistics() {
        StorageStatistics stats = new StorageStatistics();
        
        try {
            Path baseDir = Paths.get(basePath);
            
            // 统计文件数量和大小
            try (Stream<Path> paths = Files.walk(baseDir)) {
                List<Path> files = paths.filter(Files::isRegularFile).collect(Collectors.toList());
                
                long totalFiles = files.size();
                long totalSize = files.stream().mapToLong(path -> {
                    try {
                        return Files.size(path);
                    } catch (IOException e) {
                        return 0;
                    }
                }).sum();
                
                stats.setTotalFiles(totalFiles);
                stats.setTotalSize(totalSize);
            }
            
            // 获取磁盘空间信息
            File baseFile = new File(basePath);
            long usableSpace = baseFile.getUsableSpace();
            long totalSpace = baseFile.getTotalSpace();
            long usedSpace = totalSpace - usableSpace;
            
            stats.setAvailableSpace(usableSpace);
            stats.setUsedSpace(usedSpace);
            stats.setUsagePercentage((double) usedSpace / totalSpace * 100);
            
        } catch (Exception e) {
            log.error("获取存储统计失败", e);
        }
        
        return stats;
    }

    @Override
    public int cleanupTempFiles(LocalDateTime beforeTime) {
        int cleanupCount = 0;
        
        try {
            Path tempDir = Paths.get(basePath, "temp");
            if (!Files.exists(tempDir)) {
                return 0;
            }
            
            try (Stream<Path> paths = Files.walk(tempDir)) {
                List<Path> filesToDelete = paths.filter(Files::isRegularFile)
                        .filter(path -> {
                            try {
                                BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
                                LocalDateTime fileTime = LocalDateTime.ofInstant(attrs.creationTime().toInstant(), ZoneId.systemDefault());
                                return fileTime.isBefore(beforeTime);
                            } catch (IOException e) {
                                return false;
                            }
                        })
                        .collect(Collectors.toList());
                
                for (Path file : filesToDelete) {
                    try {
                        Files.delete(file);
                        cleanupCount++;
                    } catch (IOException e) {
                        log.warn("删除临时文件失败: {}", file, e);
                    }
                }
            }
            
            log.info("清理临时文件完成: {} 个文件", cleanupCount);
            
        } catch (Exception e) {
            log.error("清理临时文件失败", e);
        }
        
        return cleanupCount;
    }

    @Override
    public int cleanupExpiredFiles(LocalDateTime beforeTime) {
        int cleanupCount = 0;
        
        try {
            // 清理过期文件
            try (Stream<Path> paths = Files.walk(Paths.get(basePath))) {
                List<Path> expiredFiles = paths.filter(Files::isRegularFile)
                        .filter(path -> {
                            String fileId = extractFileIdFromPath(path);
                            FileMetadata metadata = getFileMetadata(fileId);
                            return metadata != null && 
                                   metadata.getExpireTime() != null && 
                                   metadata.getExpireTime().isBefore(beforeTime);
                        })
                        .collect(Collectors.toList());
                
                for (Path file : expiredFiles) {
                    try {
                        Files.delete(file);
                        String fileId = extractFileIdFromPath(file);
                        fileMetadataCache.remove(fileId);
                        cleanupCount++;
                    } catch (IOException e) {
                        log.warn("删除过期文件失败: {}", file, e);
                    }
                }
            }
            
            log.info("清理过期文件完成: {} 个文件", cleanupCount);
            
        } catch (Exception e) {
            log.error("清理过期文件失败", e);
        }
        
        return cleanupCount;
    }

    @Override
    public String getFileUrl(String fileId, int expireTime) {
        FileMetadata metadata = getFileMetadata(fileId);
        if (metadata == null) {
            return null;
        }
        
        // 本地文件服务直接返回文件URL，不支持过期时间
        return baseUrl + "/" + metadata.getFilePath();
    }

    @Override
    public String getPreviewUrl(String fileId) {
        FileMetadata metadata = getFileMetadata(fileId);
        if (metadata == null) {
            return null;
        }
        
        // 本地文件服务返回原文件URL作为预览URL
        return baseUrl + "/" + metadata.getFilePath();
    }

    @Override
    public boolean updateFileMetadata(String fileId, Map<String, String> metadata) {
        try {
            FileMetadata fileMetadata = getFileMetadata(fileId);
            if (fileMetadata == null) {
                return false;
            }
            
            // 更新自定义元数据
            if (fileMetadata.getCustomMetadata() == null) {
                fileMetadata.setCustomMetadata(new HashMap<>());
            }
            fileMetadata.getCustomMetadata().putAll(metadata);
            fileMetadata.setLastModified(LocalDateTime.now());
            
            // 缓存更新后的元数据
            fileMetadataCache.put(fileId, fileMetadata);
            
            log.info("文件元数据更新成功: {}", fileId);
            return true;
            
        } catch (Exception e) {
            log.error("文件元数据更新失败: {}", fileId, e);
            return false;
        }
    }

    /**
     * 从路径中提取文件ID
     */
    private String extractFileIdFromPath(Path path) {
        String fileName = path.getFileName().toString();
        // 假设文件名格式为 fileId_originalName
        int underscoreIndex = fileName.indexOf('_');
        return underscoreIndex > 0 ? fileName.substring(0, underscoreIndex) : fileName;
    }

    /**
     * 生成文件ID
     */
    private String generateFileId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 生成文件路径
     */
    private String generateFilePath(String fileName, boolean temporary) {
        String dateDir = LocalDateTime.now().toString().substring(0, 10); // yyyy-MM-dd
        String dir = temporary ? "temp" : "files";
        return dir + "/" + dateDir + "/" + generateFileId() + "_" + fileName;
    }

    /**
     * 计算文件哈希
     */
    private String calculateFileHash(Path filePath) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            try (InputStream is = Files.newInputStream(filePath);
                 DigestInputStream dis = new DigestInputStream(is, md)) {
                byte[] buffer = new byte[8192];
                while (dis.read(buffer) != -1) {
                    // Just reading to compute digest
                }
            }
            
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
            
        } catch (Exception e) {
            log.warn("计算文件哈希失败: {}", filePath, e);
            return UUID.randomUUID().toString();
        }
    }

    /**
     * 检查文件是否匹配搜索条件
     */
    private boolean matchesSearchCriteria(FileMetadata metadata, FileSearchCriteria criteria) {
        // 文件名匹配
        if (StringUtils.hasText(criteria.getFileName()) && 
            !metadata.getFileName().toLowerCase().contains(criteria.getFileName().toLowerCase())) {
            return false;
        }
        
        // 文件扩展名匹配
        if (StringUtils.hasText(criteria.getFileExtension())) {
            String fileName = metadata.getFileName();
            int dotIndex = fileName.lastIndexOf('.');
            if (dotIndex == -1 || !fileName.substring(dotIndex + 1).equalsIgnoreCase(criteria.getFileExtension())) {
                return false;
            }
        }
        
        // 内容类型匹配
        if (StringUtils.hasText(criteria.getContentType()) && 
            !Objects.equals(criteria.getContentType(), metadata.getContentType())) {
            return false;
        }
        
        // 文件大小匹配
        if (criteria.getMinSize() != null && metadata.getFileSize() < criteria.getMinSize()) {
            return false;
        }
        if (criteria.getMaxSize() != null && metadata.getFileSize() > criteria.getMaxSize()) {
            return false;
        }
        
        // 时间范围匹配
        if (criteria.getStartTime() != null && metadata.getCreateTime().isBefore(criteria.getStartTime())) {
            return false;
        }
        if (criteria.getEndTime() != null && metadata.getCreateTime().isAfter(criteria.getEndTime())) {
            return false;
        }
        
        return true;
    }
}
